
package org.openeai.lite.broker.control;

import java.net.URI;

import org.apache.activemq.broker.BrokerFactory;
import org.apache.activemq.broker.BrokerRegistry;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.broker.jmx.BrokerViewMBean;
import org.apache.activemq.web.RemoteJMXBrokerFacade;
import org.apache.activemq.web.config.SystemPropertiesConfiguration;
import org.apache.log4j.Logger;
import org.openeai.lite.common.exception.OpenEAIException;
import org.openeai.lite.common.util.Constants;
import org.openeai.lite.common.util.FileUtils;


public class ActiveMQController
{

    private static Logger log = Logger.getLogger(ActiveMQController.class);

    private static BrokerService broker = new BrokerService();

    private RemoteJMXBrokerFacade brokerFacade = null;
    
    private BrokerViewMBean brokerAdmin = null;

    private static final String PROPERTY_JMX_URL = "webconsole.jmx.url";

    private static final String PROPERTY_JMX_USER = "webconsole.jmx.user";

    private static final String PROPERTY_JMX_PASSWORD = "webconsole.jmx.password";

    // run controller as singleton
    private static volatile ActiveMQController instance;

    private static final Object instanceLock = new Object();

    private ActiveMQController()
    {
    };

    public static ActiveMQController getInstance() throws OpenEAIException
    {
        if (instance == null)
        {
            synchronized (instanceLock)
            {
                if (instance == null)
                {
                    instance = new ActiveMQController();
                }
            }
        }
        return instance;
    }

    public BrokerService getBroker()
    {
        return broker;
    }

    public BrokerService getBrokerInstance()
    {
        return BrokerRegistry.getInstance().lookup(Constants.MQ_BROKER_NAME);
    }

    
    public synchronized void start(String startupType, String configFile) throws OpenEAIException
    {
        try
        {
            if (!broker.isStarted())
            {
                String uri;
                if (startupType.equals(Constants.STARTUP_VARIANT)) {
                    uri = configFile;
                }
                else if (startupType.equals(Constants.STARTUP_CUSTOM)) {
                    uri = "xbean:" + new FileUtils().fileNameToURI(configFile).toString();
                }
                else {
                    //Unknown startup type
                    throw new OpenEAIException("Startup type " + startupType + "unknown. Cannot continue.");
                }
                
                if (org.apache.commons.lang.StringUtils.isEmpty(uri)) {
                	throw new OpenEAIException("Cannot determine URI for configuration file location.");
                }
                	
                log.info("Starting Message Broker with configuration " + uri + "\n");
                broker = BrokerFactory.createBroker(new URI(uri));
                broker.start();

                getBrokerFacade();
            }
            else
            {
                log.info("Message Broker already started.");
            }
        }
        catch (Exception e)
        {
            throw new OpenEAIException(e);
        }
    }

    // Stop the message broker
    public synchronized void stop() throws OpenEAIException
    {
        try
        {
            if (broker.isStarted())
            {
                log.info("Stopping ActiveMQ...");
                broker.stop();
            }
            else
            {
                log.info("Message Broker already stopped or stopping.");
            }
        }
        catch (Exception e)
        {
            throw new OpenEAIException(e);
        }
    }

    public boolean isStarted() throws OpenEAIException
    {
        return broker.isStarted();
    }


    public RemoteJMXBrokerFacade getBrokerFacade() throws Exception
    {
        if (brokerFacade == null)
        {
            log.info("Setting up new broker facade.");

            brokerFacade = new RemoteJMXBrokerFacade();

            System.setProperty(PROPERTY_JMX_USER, Constants.MQ_JMX_USER);
            System.setProperty(PROPERTY_JMX_PASSWORD, Constants.MQ_JMX_PASSWORD);
            System.setProperty(PROPERTY_JMX_URL, Constants.MQ_JMX_URL);
            brokerFacade.setConfiguration(new SystemPropertiesConfiguration());

            log.info("Connected to broker " + brokerFacade.getBrokerName());
        }

        return brokerFacade;
    }
    
    public BrokerViewMBean getBrokerAdmin() throws Exception
    {
        if (brokerAdmin == null)
        {
            brokerAdmin = getBrokerFacade().getBrokerAdmin();
        }
        
        return brokerAdmin;
    }


}
